package UI;

import java.text.ParseException;
import java.util.ArrayList;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import Logic.DSLogic;
import Task.DSTask;

//@author A0094762W
/**
 * DSCommandListener implements the DocumentListener interface and it is
 * responsible for analysing the commands that the user is typing, in order to
 * display appropriate feedback messages.
 */
public class DSCommandListener implements DocumentListener {

	private DSUI _userInterface;
	private DSCommandLine _commandLine;

	public DSCommandListener(DSLogic logic, DSUI userInterface) {
		_userInterface = userInterface;
		_commandLine = DSCommandLine.getInstance();
		
		_commandLine.getDocument().addDocumentListener(this);
	}
	
	//@author generated
	@Override
	public void changedUpdate(DocumentEvent ev) {
	}
	
	//@author A0094762W
	@Override
	public void removeUpdate(DocumentEvent ev) {
		_commandLine.setPlaceHolder("");
		try {
			listenCommand();
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void insertUpdate(DocumentEvent ev) {
		try {
			listenCommand();
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	private void listenCommand() throws ParseException {
		String[] currentCommand = splitCommandLineText();
		analyseCurrentCommand(currentCommand);
	}

	private String[] splitCommandLineText() {
		return _commandLine.getText().trim().split(" ");
	}

	// @author A0105536L
	/**
	 * This method is to show feedback message
	 * 
	 * @param isSuccessful
	 */
	public void feedbackMessage(boolean isSuccessful) {
		if (isSuccessful) {
			_userInterface.showMessage("Command Successful!");
		} else {
			_userInterface.showMessage("Invalid Command!");
		}
	}

	/**
	 * This method is to analyze what user is typing now. And give feedback
	 * messages or pop-up messages
	 * 
	 * @param command
	 *            String array of what user has entered.
	 * @throws ParseException
	 */
	private void analyseCurrentCommand(String[] command) throws ParseException {
		String messageString;

		if (command[0].equalsIgnoreCase("hello!")) {
			messageString = "Hi!";
			_userInterface.showMessage(messageString);
		}

		if (command.length > 1) {
			if (hasDateIndicator(command)) {
				messageString = "Eg.Jan 1st, 1st Jan, mm-dd-yyyy, mm/dd/yyyy Eg.HH:MM,5pm";
				_userInterface.showMessage(messageString);
			} else if (command[0].equalsIgnoreCase("search")) {
				String hit = "";
				ArrayList<String> keyWords = new ArrayList<String>();

				for (int k = 0; k < _userInterface.getTaskListSize(); k++) {
					String[] tempWords =
						_userInterface.getTaskFromTaskList(k).getTaskName().trim().split(" ");
					for (int j = 0; j < tempWords.length; j++) {
						keyWords.add(tempWords[j]);
					}
				}

				for (int j = 0; j < keyWords.size(); j++) {
					if (keyWords.get(j).startsWith(command[command.length - 1])) {
						if (hit == "") {
							hit = keyWords.get(j);
						} else {
							hit = "";
							break;
						}
					}
				}
				if (hit != "") {
					_commandLine.setPlaceHolder(hit
							.substring(command[command.length - 1].length()));
				} else {
					_commandLine.setPlaceHolder("");
				}

			} else if (command.length == 2) {
				if ((command[0].equalsIgnoreCase("update") || command[0]
						.equalsIgnoreCase("upd")) && isInteger(command[1])) {
					if (Integer.parseInt(command[1]) <= _userInterface.getTaskListSize()) {
						DSTask showTask =
							_userInterface.getTaskFromTaskList(Integer.parseInt(command[1]) - 1);
						_commandLine.setPlaceHolder(" "
								+ showTask.updateString());
					}
				}
			}
		} else if (command.length == 1) {
			if (command[0].equalsIgnoreCase("a")) {
				messageString = "add: add new tasks , all: display all tasks";
				_userInterface.showMessage(messageString);
			} else if (command[0].equalsIgnoreCase("d")) {
				messageString = "delete/del: delete tasks, done: mark tasks as done";
				_userInterface.showMessage(messageString);
			} else if (command[0].equalsIgnoreCase("u")) {
				messageString = "update/upd: update tasks,undo: undo your operations,undone: mark tasks as undone";
				_userInterface.showMessage(messageString);
			} else if (command[0].equalsIgnoreCase("p")) {
				messageString = "postpone/p: postpone a task by 1 day";
				_userInterface.showMessage(messageString);
			} else if (command[0].equalsIgnoreCase("o")) {
				messageString = "overdue: all overdue tasks";
				_userInterface.showMessage(messageString);
			} else if (command[0].equalsIgnoreCase("s")) {
				messageString = "search";
				_userInterface.showMessage(messageString);
			}
		} else {
			_commandLine.setPlaceHolder("");
		}
	}

	/**
	 * This method is to check whether a string array contains date indicators
	 * 
	 * @param command
	 *            A string array
	 * @return Return true, if the string has some date indicators
	 */
	private static boolean hasDateIndicator(String[] command) {
		return command[command.length - 1].equalsIgnoreCase("from")
				|| command[command.length - 1].equalsIgnoreCase("on")
				|| command[command.length - 1].equalsIgnoreCase("by")
				|| command[command.length - 2].equalsIgnoreCase("from")
				|| command[command.length - 2].equalsIgnoreCase("on")
				|| command[command.length - 2].equalsIgnoreCase("by");
	}

	/**
	 * This method is to check if there is only integer in a given string
	 * 
	 * @param integerString
	 *            String to be checked
	 * @return True if the string contains only integer. e.g "123"-->true;
	 *         "123abc"-->false
	 */
	private static boolean isInteger(String integerString) {

		try {
			Integer.parseInt(integerString);
			return true;
		} catch (NumberFormatException nfe) {
			return false;
		}
	}
}
